// const defaultOption = {
// 	duration: 300,
// 	timingFunction: 'linear',
// 	delay: 0,
// 	transformOrigin: '50% 50% 0'
// }
// #ifdef APP-NVUE
const nvueAnimation = uni.requireNativePlugin('animation')
// #endif
class MPAnimation {
  constructor(options, _this) {
    this.options = options
    // 在iOS10+QQ小程序平台下，传给原生的对象一定是个普通对象而不是Proxy对象，否则会报parameter should be Object instead of ProxyObject的错误
    this.animation = uni.createAnimation({
      ...options,
    })
    this.currentStepAnimates = {}
    this.next = 0
    this.$ = _this
  }

  _nvuePushAnimates(type, args) {
    let aniObj = this.currentStepAnimates[this.next]
    let styles = {}
    if (!aniObj) {
      styles = {
        styles: {},
        config: {},
      }
    } else {
      styles = aniObj
    }
    if (animateTypes1.includes(type)) {
      if (!styles.styles.transform) {
        styles.styles.transform = ''
      }
      let unit = ''
      if (type === 'rotate') {
        unit = 'deg'
      }
      styles.styles.transform += `${type}(${args + unit}) `
    } else {
      styles.styles[type] = `${args}`
    }
    this.currentStepAnimates[this.next] = styles
  }
  _animateRun(styles = {}, config = {}) {
    let ref = this.$.$refs['ani'].ref
    if (!ref) return
    return new Promise((resolve, reject) => {
      nvueAnimation.transition(
        ref,
        {
          styles,
          ...config,
        },
        (res) => {
          resolve()
        }
      )
    })
  }

  _nvueNextAnimate(animates, step = 0, fn) {
    let obj = animates[step]
    if (obj) {
      let { styles, config } = obj
      this._animateRun(styles, config).then(() => {
        step += 1
        this._nvueNextAnimate(animates, step, fn)
      })
    } else {
      this.currentStepAnimates = {}
      typeof fn === 'function' && fn()
      this.isEnd = true
    }
  }

  step(config = {}) {
    // #ifndef APP-NVUE
    this.animation.step(config)
    // #endif
    // #ifdef APP-NVUE
    this.currentStepAnimates[this.next].config = Object.assign(
      {},
      this.options,
      config
    )
    this.currentStepAnimates[this.next].styles.transformOrigin =
      this.currentStepAnimates[this.next].config.transformOrigin
    this.next++
    // #endif
    return this
  }

  run(fn) {
    // #ifndef APP-NVUE
    this.$.animationData = this.animation.export()
    this.$.timer = setTimeout(() => {
      typeof fn === 'function' && fn()
    }, this.$.durationTime)
    // #endif
    // #ifdef APP-NVUE
    this.isEnd = false
    let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref
    if (!ref) return
    this._nvueNextAnimate(this.currentStepAnimates, 0, fn)
    this.next = 0
    // #endif
  }
}

const animateTypes1 = [
  'matrix',
  'matrix3d',
  'rotate',
  'rotate3d',
  'rotateX',
  'rotateY',
  'rotateZ',
  'scale',
  'scale3d',
  'scaleX',
  'scaleY',
  'scaleZ',
  'skew',
  'skewX',
  'skewY',
  'translate',
  'translate3d',
  'translateX',
  'translateY',
  'translateZ',
]
const animateTypes2 = ['opacity', 'backgroundColor']
const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom']
animateTypes1.concat(animateTypes2, animateTypes3).forEach((type) => {
  MPAnimation.prototype[type] = function (...args) {
    // #ifndef APP-NVUE
    this.animation[type](...args)
    // #endif
    // #ifdef APP-NVUE
    this._nvuePushAnimates(type, args)
    // #endif
    return this
  }
})

export function createAnimation(option, _this) {
  if (!_this) return
  clearTimeout(_this.timer)
  return new MPAnimation(option, _this)
}
